home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Interactive Reference Guide / C-C++ Interactive Reference Guide.iso / c_ref / csource5 / 365_01 / main.c < prev    next >
C/C++ Source or Header  |  1992-04-06  |  11KB  |  517 lines

  1. /* main.c */
  2.  
  3. /* Author:
  4.  *    Steve Kirkendall
  5.  *    14407 SW Teal Blvd. #C
  6.  *    Beaverton, OR 97005
  7.  *    kirkenda@cs.pdx.edu
  8.  */
  9.  
  10.  
  11. /* This file contains the main() function of vi */
  12.  
  13. /* HACK! bcc needs to disable use of precompiled headers for this file,
  14.    or else command line args will not be passed to elvis */
  15. #if __BORLANDC__
  16. #include "borland.h"
  17. #endif
  18.  
  19. #include "config.h"
  20. #include <setjmp.h>
  21. #include "vi.h"
  22.  
  23. extern        trapint(); /* defined below */
  24. extern char    *getenv();
  25. jmp_buf        jmpenv;
  26.  
  27. #ifndef NO_DIGRAPH
  28. static init_digraphs();
  29. #endif
  30.  
  31. /*---------------------------------------------------------------------*/
  32.  
  33. #if AMIGA
  34. # include "amiwild.c"
  35. main (argc, argv)
  36. #else
  37. # if VMS
  38. #  include "vmswild.c"
  39. main (argc, argv)
  40. # else
  41. void main(argc, argv)
  42. # endif
  43. #endif
  44.     int    argc;
  45.     char    *argv[];
  46. {
  47.     int    i;
  48.     char    *cmd = (char *)0;
  49.     char    *err = (char *)0;
  50.     char    *str;
  51.     char    *tag = (char *)0;
  52.  
  53.     /* set mode to MODE_VI or MODE_EX depending on program name */
  54.     switch (argv[0][strlen(argv[0]) - 1])
  55.     {
  56.       case 'x':            /* "ex" */
  57.         mode = MODE_EX;
  58.         break;
  59.  
  60.       case 'w':            /* "view" */
  61.         mode = MODE_VI;
  62.         *o_readonly = TRUE;
  63.         break;
  64. #ifndef NO_EXTENSIONS
  65.       case 't':            /* "edit" or "input" */
  66.         mode = MODE_VI;
  67.         *o_inputmode = TRUE;
  68.         break;
  69. #endif
  70.       default:            /* "vi" or "elvis" */
  71.         mode = MODE_VI;
  72.     }
  73.  
  74. #ifndef DEBUG
  75. # ifdef    SIGQUIT
  76.     /* normally, we ignore SIGQUIT.  SIGINT is trapped later */
  77.     signal(SIGQUIT, SIG_IGN);
  78. # endif
  79. #endif
  80.  
  81.     /* temporarily ignore SIGINT */
  82.     signal(SIGINT, SIG_IGN);
  83.  
  84.     /* start curses */
  85.     initscr();
  86.     cbreak();
  87.     noecho();
  88.     scrollok(stdscr, TRUE);
  89.  
  90.     /* arrange for deadly signals to be caught */
  91. # ifdef SIGHUP
  92.     signal(SIGHUP, (void(*)()) deathtrap);
  93. # endif
  94. # ifndef DEBUG
  95. #  ifdef SIGILL
  96.     signal(SIGILL, (void(*)()) deathtrap);
  97. #  endif
  98. #  ifdef SIGBUS
  99.     signal(SIGBUS, (void(*)()) deathtrap);
  100. #  endif
  101. #  ifdef SIGSEGV
  102.     signal(SIGSEGV, (void(*)()) deathtrap);
  103. #  endif
  104. #  ifdef SIGSYS
  105.     signal(SIGSYS, (void(*)()) deathtrap);
  106. #  endif
  107. # endif /* !DEBUG */
  108. # ifdef SIGPIPE
  109.     signal(SIGPIPE, (void(*)()) deathtrap);
  110. # endif
  111. # ifdef SIGTERM
  112.     signal(SIGTERM, (void(*)()) deathtrap);
  113. # endif
  114. # ifdef SIGUSR1
  115.     signal(SIGUSR1, (void(*)()) deathtrap);
  116. # endif
  117. # ifdef SIGUSR2
  118.     signal(SIGUSR2, (void(*)()) deathtrap);
  119. # endif
  120.  
  121.     /* initialize the options - must be done after initscr(), so that
  122.      * we can alter LINES and COLS if necessary.
  123.      */
  124.     initopts();
  125.  
  126.     /* map the arrow keys.  The KU,KD,KL,and KR variables correspond to
  127.      * the :ku=: (etc.) termcap capabilities.  The variables are defined
  128.      * as part of the curses package.
  129.      */
  130.     if (has_KU) mapkey(has_KU, "k",    WHEN_VICMD|WHEN_INMV, "<Up>");
  131.     if (has_KD) mapkey(has_KD, "j",    WHEN_VICMD|WHEN_INMV, "<Down>");
  132.     if (has_KL) mapkey(has_KL, "h",    WHEN_VICMD|WHEN_INMV, "<Left>");
  133.     if (has_KR) mapkey(has_KR, "l",    WHEN_VICMD|WHEN_INMV, "<Right>");
  134.     if (has_HM) mapkey(has_HM, "^",    WHEN_VICMD|WHEN_INMV, "<Home>");
  135.     if (has_EN) mapkey(has_EN, "$",    WHEN_VICMD|WHEN_INMV, "<End>");
  136.     if (has_PU) mapkey(has_PU, "\002", WHEN_VICMD|WHEN_INMV, "<PageUp>");
  137.     if (has_PD) mapkey(has_PD, "\006", WHEN_VICMD|WHEN_INMV, "<PageDn>");
  138.     if (has_KI) mapkey(has_KI, "i",    WHEN_VICMD|WHEN_INMV, "<Insert>");
  139. #if MSDOS
  140. # if RAINBOW
  141.     if (!strcmp("rainbow", o_term))
  142.     {
  143.         mapkey("\033[1~",  "/",        WHEN_VICMD,        "<Find>");
  144.         mapkey("\033[3~",  "x",        WHEN_VICMD|WHEN_INMV,    "<Remove>");
  145.         mapkey("\033[4~",  "v",        WHEN_VICMD|WHEN_INMV,    "<Select>");
  146.         mapkey("\033[17~", ":sh\n",    WHEN_VICMD,        "<Intrpt>");
  147.         mapkey("\033[19~", ":q\n",    WHEN_VICMD,        "<Cancel>");
  148.         mapkey("\033[21~", "ZZ",    WHEN_VICMD,        "<Exit>");
  149.         mapkey("\033[26~", "V",        WHEN_VICMD|WHEN_INMV,    "<AddlOp>");
  150.         mapkey("\033[28~", "\\",    WHEN_VICMD|WHEN_INMV,    "<Help>");
  151.         mapkey("\033[29~", "K",        WHEN_VICMD|WHEN_INMV,    "<Do>");
  152.     }
  153.     else
  154. # endif /* RAINBOW */
  155.     {
  156.         mapkey("#S", "x", WHEN_VICMD|WHEN_INMV,    "<Delete>");
  157.         mapkey("#s", "B", WHEN_VICMD|WHEN_INMV,    "^<Left>");
  158.         mapkey("#t", "W", WHEN_VICMD|WHEN_INMV,    "^<Right>");
  159.     }
  160. #else /* not MSDOS */
  161. # if COHERENT
  162.     mapkey("\033[P", "x", WHEN_VICMD|WHEN_INMV, "<Del>");
  163. # else
  164. #if AMIGA
  165.     mapkey("\233?~", "\\",    WHEN_VICMD|WHEN_INMV,    "<Help>");
  166. #endif
  167.  
  168.     if (ERASEKEY != '\177')
  169.     {
  170.         mapkey("\177", "x", WHEN_VICMD|WHEN_INMV, "<Del>");
  171.     }
  172. # endif
  173. #endif
  174.  
  175. #ifndef NO_DIGRAPH
  176.     init_digraphs();
  177. #endif /* NO_DIGRAPH */
  178.  
  179.     /* process any flags */
  180.     for (i = 1; i < argc && *argv[i] == '-'; i++)
  181.     {
  182.         switch (argv[i][1])
  183.         {
  184.           case 'R':    /* readonly */
  185.             *o_readonly = TRUE;
  186.             break;
  187.  
  188.           case 'L':
  189.           case 'r':    /* recover */
  190.             msg("Use the `elvrec` program to recover lost files");
  191.             endmsgs();
  192.             refresh();
  193.             endwin();
  194.             exit(0);
  195.             break;
  196.  
  197.           case 't':    /* tag */
  198.             if (argv[i][2])
  199.             {
  200.                 tag = argv[i] + 2;
  201.             }
  202.             else
  203.             {
  204.                 tag = argv[++i];
  205.             }
  206.             break;
  207.  
  208.           case 'v':    /* vi mode */
  209.             mode = MODE_VI;
  210.             break;
  211.  
  212.           case 'e':    /* ex mode */
  213.             mode = MODE_EX;
  214.             break;
  215. #ifndef NO_EXTENSIONS
  216.           case 'i':    /* input mode */
  217.             *o_inputmode = TRUE;
  218.             break;
  219. #endif
  220. #ifndef NO_ERRLIST
  221.           case 'm':    /* use "errlist" as the errlist */
  222.             if (argv[i][2])
  223.             {
  224.                 err = argv[i] + 2;
  225.             }
  226.             else if (i + 1 < argc)
  227.             {
  228.                 err = argv[++i];
  229.             }
  230.             else
  231.             {
  232.                 err = "";
  233.             }
  234.             break;
  235. #endif
  236. #ifndef CRUNCH
  237.          case 'c':    /* run the following command, later */
  238.             if (argv[i][2])
  239.             {
  240.                 cmd = argv[i] + 2;
  241.             }
  242.             else
  243.             {
  244.                 cmd = argv[++i];
  245.             }
  246.             break;
  247.  
  248.           case 'w':    /* set the window size */
  249.             if (argv[i][2])
  250.             {
  251.                 *o_window = atoi(argv[i] + 2);
  252.                 wset = TRUE;
  253.             }
  254.             else
  255.             {
  256.                 *o_window = atoi(argv[++i]);
  257.                 wset = TRUE;
  258.             }
  259.             break;
  260. #endif
  261.           default:
  262.             msg("Ignoring unknown flag \"%s\"", argv[i]);
  263.         }
  264.     }
  265.  
  266.     /* if we were given an initial ex command, save it... */
  267.     if (i < argc && *argv[i] == '+')
  268.     {
  269.         if (argv[i][1])
  270.         {
  271.             cmd = argv[i++] + 1;
  272.         }
  273.         else
  274.         {
  275.             cmd = "$"; /* "vi + file" means start at EOF */
  276.             i++;
  277.         }
  278.     }
  279.  
  280.     /* the remaining args are file names. */
  281.     if (i < argc)
  282.     {
  283.         strcpy(args, argv[i]);
  284.         while (++i < argc && strlen(args) + 1 + strlen(argv[i]) < sizeof args)
  285.         {
  286.             strcat(args, " ");
  287.             strcat(args, argv[i]);
  288.         }
  289. #if MSDOS || TOS
  290.         /* expand wildcard characters, if necessary */
  291.         if (strchr(args, '*') || strchr(args, '?'))
  292.         {
  293.             strcpy(args, wildcard(args));
  294.         }
  295. #endif
  296.         strcpy(tmpblk.c, args);
  297.         cmd_args(MARK_UNSET, MARK_UNSET, CMD_ARGS, TRUE, tmpblk.c);
  298.     }
  299.     else
  300.     {
  301.         /* empty args list */
  302.         args[0] = '\0';
  303.         nargs = 1;
  304.         argno = -1;
  305.     }
  306.  
  307.     /* perform the .exrc files and EXINIT environment variable */
  308. #ifdef SYSEXRC
  309.     doexrc(SYSEXRC);
  310. #endif
  311. #ifdef HMEXRC
  312.     str = getenv("HOME");
  313.     if (str && *str)
  314.     {
  315.         strcpy(tmpblk.c, str);
  316.         str = tmpblk.c + strlen(tmpblk.c);
  317. #if !VMS
  318. # if AMIGA    /* Don't SLASH a device. "Elvis:.exrc" */
  319.         if (str[-1] != COLON && str[-1] != SLASH)
  320. # else
  321.         if (str[-1] != SLASH)
  322. # endif
  323.         {
  324.             *str++ = SLASH;
  325.         }
  326. #endif
  327.         strcpy(str, HMEXRC);
  328.         doexrc(tmpblk.c);
  329.     }
  330. #endif
  331. #ifndef CRUNCH
  332.     if (*o_exrc)
  333. #endif
  334.     {
  335.         doexrc(EXRC);
  336.     }
  337. #ifdef EXINIT
  338.     str = getenv(EXINIT);
  339.     if (str)
  340.     {
  341.         exstring(str, strlen(str), ctrl('V'));
  342.     }
  343. #endif
  344.  
  345.     /* search for a tag (or an error) now, if desired */
  346.     blkinit();
  347.     if (tag)
  348.     {
  349.         cmd_tag(MARK_FIRST, MARK_FIRST, CMD_TAG, 0, tag);
  350.     }
  351. #ifndef NO_ERRLIST
  352.     else if (err)
  353.     {
  354.         cmd_errlist(MARK_FIRST, MARK_FIRST, CMD_ERRLIST, 0, err);
  355.     }
  356. #endif
  357.  
  358.     /* if no tag/err, or tag failed, then start with first arg */
  359.     if (tmpfd < 0)
  360.     {
  361.         /* start with first arg */
  362.         cmd_next(MARK_UNSET, MARK_UNSET, CMD_NEXT, FALSE, "");
  363.  
  364.         /* pretend to do something, just to force a recoverable
  365.          * version of the file out to disk
  366.          */
  367.         ChangeText
  368.         {
  369.         }
  370.         clrflag(file, MODIFIED);
  371.     }
  372.  
  373.     /* now we do the immediate ex command that we noticed before */
  374.     if (cmd)
  375.     {
  376.         doexcmd(cmd);
  377.     }
  378.  
  379.     /* repeatedly call ex() or vi() (depending on the mode) until the
  380.      * mode is set to MODE_QUIT
  381.      */
  382.     while (mode != MODE_QUIT)
  383.     {
  384.         if (setjmp(jmpenv))
  385.         {
  386.             /* Maybe we just aborted a change? */
  387.             abortdo();
  388.         }
  389.         signal(SIGINT, (void(*)()) trapint);
  390.  
  391.         switch (mode)
  392.         {
  393.           case MODE_VI:
  394.             vi();
  395.             break;
  396.  
  397.           case MODE_EX:
  398.             ex();
  399.             break;
  400. #ifdef DEBUG
  401.           default:
  402.             msg("mode = %d?", mode);
  403.             mode = MODE_QUIT;
  404. #endif
  405.         }
  406.     }
  407.  
  408.     /* free up the cut buffers */
  409.     cutend();
  410.  
  411.     /* end curses */
  412. #ifndef    NO_CURSORSHAPE
  413.     if (has_CQ)
  414.         do_CQ();
  415. #endif
  416.     endmsgs();
  417.     move(LINES - 1, 0);
  418.     clrtoeol();
  419.     refresh();
  420.     endwin();
  421.  
  422.     exit(0);
  423.     /*NOTREACHED*/
  424. }
  425.  
  426.  
  427. /*ARGSUSED*/
  428. int trapint(signo)
  429.     int    signo;
  430. {
  431.     beep();
  432.     resume_curses(FALSE);
  433.     abortdo();
  434. #if OSK
  435.     sigmask(-1);
  436. #endif
  437. #if TURBOC || __GNUC__
  438.     signal(signo, (void (*)())trapint);
  439. #else
  440.     signal(signo, trapint);
  441. #endif
  442.     doingglobal = FALSE;
  443.  
  444.     longjmp(jmpenv, 1);
  445.  
  446.     return 0;
  447. }
  448.  
  449.  
  450.  
  451. #ifndef NO_DIGRAPH
  452.  
  453. /* This stuff us used to build the default digraphs table. */
  454. static char    digtable[][4] =
  455. {
  456. # ifdef CS_IBMPC
  457.     "C,\200",    "u\"\1",    "e'\2",        "a^\3",
  458.     "a\"\4",    "a`\5",        "a@\6",        "c,\7",
  459.     "e^\10",    "e\"\211",    "e`\12",    "i\"\13",
  460.     "i^\14",    "i`\15",    "A\"\16",    "A@\17",
  461.     "E'\20",    "ae\21",    "AE\22",    "o^\23",
  462.     "o\"\24",    "o`\25",    "u^\26",    "u`\27",
  463.     "y\"\30",    "O\"\31",    "U\"\32",    "a'\240",
  464.     "i'!",        "o'\"",        "u'#",        "n~$",
  465.     "N~%",        "a-&",        "o-'",        "~?(",
  466.     "~!-",        "\"<.",        "\">/",
  467. #  ifdef CS_SPECIAL
  468.     "2/+",        "4/,",        "^+;",        "^q<",
  469.     "^c=",        "^r>",        "^t?",        "pp]",
  470.     "^^^",        "oo_",        "*a`",        "*ba",
  471.     "*pc",        "*Sd",        "*se",        "*uf",
  472.     "*tg",        "*Ph",        "*Ti",        "*Oj",
  473.     "*dk",        "*Hl",        "*hm",        "*En",
  474.     "*No",        "eqp",        "pmq",        "ger",
  475.     "les",        "*It",        "*iu",        "*/v",
  476.     "*=w",        "sq{",        "^n|",        "^2}",
  477.     "^3~",        "^_\377",
  478. #  endif /* CS_SPECIAL */
  479. # endif /* CS_IBMPC */
  480. # ifdef CS_LATIN1
  481.     "~!!",        "a-*",        "\">+",        "o-:",
  482.     "\"<>",        "~??",
  483.  
  484.     "A`@",        "A'A",        "A^B",        "A~C",
  485.     "A\"D",        "A@E",        "AEF",        "C,G",
  486.     "E`H",        "E'I",        "E^J",        "E\"K",
  487.     "I`L",        "I'M",        "I^N",        "I\"O",
  488.     "-DP",        "N~Q",        "O`R",        "O'S",
  489.     "O^T",        "O~U",        "O\"V",        "O/X",
  490.     "U`Y",        "U'Z",        "U^[",        "U\"\\",
  491.     "Y'_",
  492.  
  493.     "a``",        "a'a",        "a^b",        "a~c",
  494.     "a\"d",        "a@e",        "aef",        "c,g",
  495.     "e`h",        "e'i",        "e^j",        "e\"k",
  496.     "i`l",        "i'm",        "i^n",        "i\"o",
  497.     "-dp",        "n~q",        "o`r",        "o's",
  498.     "o^t",        "o~u",        "o\"v",        "o/x",
  499.     "u`y",        "u'z",        "u^{",        "u\"|",
  500.     "y'~",
  501. # endif /* CS_LATIN1 */
  502.     ""
  503. };
  504.  
  505. static init_digraphs()
  506. {
  507.     int    i;
  508.  
  509.     for (i = 0; *digtable[i]; i++)
  510.     {
  511.         do_digraph(FALSE, digtable[i]);
  512.     }
  513.     do_digraph(FALSE, (char *)0);
  514.     return 0;
  515. }
  516. #endif /* NO_DIGRAPH */
  517.